using System;
using System.Collections.Generic;
using System.Text;
using System.Collections.ObjectModel;
using OnlinePlots.Diagrams;
using System.Windows.Shapes;
using System.Windows.Media;
using System.Windows;
using System.Linq;
using System.Windows.Controls;
using System.Windows.Data;

namespace OnlinePlots.Plots.Elements
{
    /// <summary>
    /// Represents plot line element of a plot
    /// </summary>
    public class PlotLineElement : DiagramElement
    {
        /// <summary>
        /// Creates a new instance of plot line element
        /// </summary>
        public PlotLineElement()
            : base()
        {
        }

        new public static readonly DependencyProperty ZOrderProperty = DependencyProperty.Register(
                "ZOrder",
                typeof(int),
                typeof(PlotLineElement),
                new PropertyMetadata(500)
            );

        public static readonly DependencyProperty BrushProperty = DependencyProperty.Register(
                        "Brush",
                        typeof(Brush),
                        typeof(PlotLineElement),
                        new PropertyMetadata(new SolidColorBrush(Colors.Blue), new PropertyChangedCallback(OnBrushPropertyChanged))
                    );

        /// <summary>
        /// Gets or sets brush of the plot line
        /// </summary>
        public Brush Brush
        {
            get { return (Brush)GetValue(BrushProperty); }
            set { SetValue(BrushProperty, value); }
        }

        static protected void OnBrushPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            DiagramElement el = d as DiagramElement;
            el.NotifyPropertyChanged("Brush");
        }

        public static readonly DependencyProperty OpacityProperty = DependencyProperty.Register(
                        "Opacity",
                        typeof(double),
                        typeof(PlotLineElement),
                        new PropertyMetadata(1.0, new PropertyChangedCallback(OnOpacityPropertyChanged))
                    );

        public double Opacity
        {
            get { return (double)GetValue(OpacityProperty); }
            set { SetValue(OpacityProperty, value); }
        }

        static protected void OnOpacityPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            DiagramElement el = d as DiagramElement;
            el.NotifyPropertyChanged("Opacity");
        }

        public static readonly DependencyProperty ThicknessProperty = DependencyProperty.Register(
                        "Thickness",
                        typeof(double),
                        typeof(PlotLineElement),
                        new PropertyMetadata(1.0, new PropertyChangedCallback(OnThicknessPropertyChanged))
                    );

        public double Thickness
        {
            get { return (double)GetValue(ThicknessProperty); }
            set { SetValue(ThicknessProperty, value); }
        }

        static protected void OnThicknessPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            DiagramElement el = d as DiagramElement;
            el.NotifyPropertyChanged("Thickness");
        }

        internal void AddPolyline(List<Point> points)
        {
            Polyline newPolyline = new Polyline();

            newPolyline.SetBinding(Polyline.StrokeProperty, new Binding() { Source = Brush });
            newPolyline.SetBinding(Polyline.StrokeThicknessProperty, new Binding() { Source = Thickness });
            newPolyline.SetBinding(Polyline.OpacityProperty, new Binding() { Source = Opacity });
            newPolyline.SetBinding(Canvas.ZIndexProperty, new Binding() { Source = ZOrder });

            points.ForEach(point => newPolyline.Points.Add(point));
            shapes.Add(newPolyline);
        }

        /// <summary>
        /// Gets array of polyline shapes associated with the element
        /// </summary>
        public ReadOnlyCollection<Polyline> Polylines
        {
            get
            {
                return shapes.Cast<Polyline>().ToList().AsReadOnly();
            }
        }
    }
}
